#include "ArrayList.h"

BASE(ArrayList, List, 100)

#define SIZE_INCREMENT 10

//HIDDEN
IMPL(int, resize, unsigned int newSize)
{
	void *result = realloc(THIS->objs, sizeof(void *)*newSize);
	if(!result) return 0;
	THIS->maxSize = newSize;
	THIS->objs = result;

	return 1;
}

//SHARED
IMPL(void, destroy)
{

	if(THIS->objs)
	{
		int i;
		for(i=0; i<C(size)(); i++) { D(THIS->objs[i]); }
		free(THIS->objs);
	}

}

IMPL(unsigned long, size)
{
	RETURN THIS->size;
}

IMPL(int, isEmpty)
{
	RETURN THIS->size==0;
}

IMPL(int, add, void *ptr)
{
	if(THIS->size==THIS->maxSize)
	{
		if(!resize(THIS, THIS->size+SIZE_INCREMENT)) return 0;
	}

	THIS->objs[THIS->size] = R(ptr);
	THIS->size++;

	return 1;
}

IMPL(int, insertAt, unsigned long int pos, void *ptr)
{
	if(THIS->size<=pos)
	{
		if(!resize(THIS, pos+SIZE_INCREMENT)) return 0;
	}
	else if(THIS->size==THIS->maxSize)
	{
		if(!resize(THIS, THIS->size+SIZE_INCREMENT)) return 0;
	}

	int i;
	for(i=THIS->size; i>pos; i--)
	{
		THIS->objs[i] = THIS->objs[i-1];
	}

	THIS->objs[pos] = R(ptr);
	THIS->size = pos>=THIS->size?pos+1:THIS->size+1;

	return 1;
}

IMPL(int, set, unsigned long int pos, void *ptr)
{
	if(THIS->size<=pos) return 0;

	D(THIS->objs[pos]);

	THIS->objs[pos] = R(ptr);
	THIS->size = pos>=THIS->size?pos+1:THIS->size;

	return 1;
}

IMPL(void *, get, unsigned long int pos)
{
	if(pos>=THIS->size) return INVALID_OBJ;

	return THIS->objs[pos];
}

IMPL(long int, indexOf, void *ptr)
{
	int i;
	for(i=0; i<THIS->size; i++)
	{
		if(THIS->objs[i] == ptr) return i;
	}

	return -1;
}

IMPL(long int, lastIndexOf, void *ptr)
{
	int i;
	for(i=THIS->size-1; i>=0; i--)
	{
		if(THIS->objs[i] == ptr) return i;
	}

	return -1;
}

IMPL(int, contains, void *ptr)
{
	int i;
	for(i=0; i<THIS->size; i++)
	{
		if(THIS->objs[i] == ptr) return 1;
	}

	return 0;
}

IMPL(int, del, unsigned long int pos)
{
	int i;

	if(pos>=THIS->size) return 0;

	D(THIS->objs[pos]);

	for(i=pos; i<(THIS->size-1); i++)
	{
		THIS->objs[i] = THIS->objs[i+1];
	}

	THIS->size--;

	if( (THIS->size+SIZE_INCREMENT) < (THIS->maxSize/2) )
	{
		resize(THIS, THIS->size+SIZE_INCREMENT);
	}

	return 1;
}

IMPL(int, delObj, void *ptr)
{
	long int pos = C(indexOf)(ptr);

	if(pos==-1) return 0;

	C(del)(pos);

	return 1;
}

SETUP_IF(ENTRY(size), ENTRY(isEmpty), ENTRY(destroy),
ENTRY(add), ENTRY(insertAt),
ENTRY(set), ENTRY(get),
ENTRY(indexOf), ENTRY(lastIndexOf), ENTRY(contains),
ENTRY(del), ENTRY(delObj) )
